﻿using System;
using System.Xml;

using pt = System.UInt32;

namespace RDLC
{
   public abstract class ReportItem
   {
      protected string _Name;

      public pt Top { get { return _Position.Top; } }
      public pt Left { get { return _Position.Left; } }
      public pt? Width { get { return _Position.Width; } }
      public pt? Height { get { return _Position.Height; } }

      protected RDLPosition _Position;
      //note: Bookmark element not implemented
      //note: Custom element not implemented
      public string Label; // Optional
      public RDLVisibility Visibility; // Optional
      
      private readonly string _Type;
      protected readonly RDLStyle _Style;
      public uint? ZIndex
      {
         get { return _ZIndex; }
         set
         {
            if(!_ZIndex.HasValue)
               _ZIndex = new uint();
            _ZIndex = value;
         }
      }
      private uint? _ZIndex;

      protected ReportItem(string name, string type, RDLPosition position, RDLStyle style)
      {
         _Name = name;
         _Type = type;
         _Style = style;
         _Position = position;         
      }

      protected abstract void WriteDetails(XmlTextWriter writer);

      public void Write(XmlTextWriter writer)
      {
         writer.WriteStartElement(_Type);
         writer.WriteAttributeString("Name", null, _Name);
     
         if(_Position != null)
            _Position.Write(writer);

         WriteDetails(writer);

         if(Visibility != null)
            Visibility.Write(writer);

         if(_Style != null)
            _Style.Write(writer);

         if(Label != null)
            writer.WriteElementString("Label", Label);

         if(ZIndex.HasValue)
            writer.WriteElementString("ZIndex", ZIndex.Value.ToString());

         writer.WriteEndElement(); // ReportItem type
      }
   }

   public class RDLVisibility
   {
      public bool Hidden
      {
         set { HiddenExp = value ? "true" : "false"; }
      }
      public string HiddenExp; // Optional

      public string ToggleItem; // Optional

      public void Write(XmlTextWriter writer)
      {
         writer.WriteStartElement("Visibility");

         if(HiddenExp != null)
            writer.WriteElementString("Hidden", HiddenExp);

         if(ToggleItem != null)
            writer.WriteElementString("ToggleItem", ToggleItem);

         writer.WriteEndElement(); // Visibility
      }
   }

   internal enum RDLReportItem
   {
      Line,
      Rectangle,
      TextBox,
      Image,
      Subreport,
      List,
      Matrix,
      Table,
      Chart,
      Body,
      Subtotal
   };

   public class RDLLine : ReportItem
   {
      public string RepeatWith; // Optional

      public RDLLine(string name, RDLPosition position, LineStyle style) 
         : base(name, "Line", position, style)
      {
      }

      protected override void WriteDetails(XmlTextWriter writer)
      {
         if(RepeatWith != null)
            writer.WriteElementString("RepeatWith", RepeatWith);
      }
   }

   public class RDLImage
   {
      public RDLStyle.RDLImageSource Source;
      public string Value;
      public RDLStyle.ImageMimeType? MIMEType
      {
         get { return _MIMEType; }
         set
         {
            if(!_MIMEType.HasValue)
               _MIMEType = new RDLStyle.ImageMimeType();
            _MIMEType = value;
         }
      }

      private RDLStyle.ImageMimeType? _MIMEType;
      public RDLStyle.RDLBackgroundRepeat? BackgroundRepeat
      {
         get { return _BackgroundRepeat; }
         set
         {
            if(!_BackgroundRepeat.HasValue)
               _BackgroundRepeat = new RDLStyle.RDLBackgroundRepeat();
            _BackgroundRepeat = value;
         }
      }
      private RDLStyle.RDLBackgroundRepeat? _BackgroundRepeat;

      public enum ImageType { Background, Standard }

      private ImageType _ImageType;

      public RDLImage(ImageType imageType, RDLStyle.RDLImageSource source, string value)
      {
         _ImageType = imageType;
         Source = source;
         Value = value;
      }

      public void Write(XmlTextWriter writer)
      {
         if(_ImageType == ImageType.Background)
         {
            writer.WriteStartElement("BackgroundImage");
         }
         else
         {
            writer.WriteStartElement("Image");
         }

         if(BackgroundRepeat.HasValue)
            writer.WriteElementString("BackgroundRepeat", BackgroundRepeat.Value.ToString());

         if(MIMEType.HasValue)
            writer.WriteElementString("MIMEType", MIMEType.Value.ToString());

         writer.WriteElementString("Source", Source.ToString());
         writer.WriteElementString("Value", Value);

         writer.WriteEndElement(); // BackgroundImage, Image
      }
   }

   public class LineStyle : RDLStyle
   {
      public LineStyle()
      {
         
      }

      public LineStyle(RDLBorderColor borderColor, RDLBorderStyle borderStyle, RDLBorderWidth borderWidth) 
         : base(borderColor, borderStyle, borderWidth)
      {
      }

      protected override void WriteDetails(XmlTextWriter writer)
      {

      }
   }

   internal class ImageStyle : RDLStyle
   {
      public RDLPadding Padding;

      public ImageStyle(RDLBorderColor borderColor, RDLBorderStyle borderStyle, RDLBorderWidth borderWidth) 
         : base(borderColor, borderStyle, borderWidth)
      {
      }

      protected override void WriteDetails(XmlTextWriter writer)
      {
         throw new NotImplementedException();
      }
   }

   internal class SubreportStyle : RDLStyle
   {
      public SubreportStyle(RDLBorderColor borderColor, RDLBorderStyle borderStyle, RDLBorderWidth borderWidth) 
         : base(borderColor, borderStyle, borderWidth)
      {
      }

      protected override void WriteDetails(XmlTextWriter writer)
      {
         throw new NotImplementedException();
      }
   }

   internal class ListStyle : RDLStyle
   {
      public RDLColor BackgroundColor;
      public RDLImage BackgroundImage;

      public ListStyle(RDLBorderColor borderColor, RDLBorderStyle borderStyle, RDLBorderWidth borderWidth) 
         : base(borderColor, borderStyle, borderWidth)
      {
      }

      protected override void WriteDetails(XmlTextWriter writer)
      {
         throw new NotImplementedException();
      }
   }

   internal class MatrixStyle : RDLStyle
   {
      public RDLColor BackgroundColor;
      public RDLImage BackgroundImage;

      public MatrixStyle(RDLBorderColor borderColor, RDLBorderStyle borderStyle, RDLBorderWidth borderWidth) 
         : base(borderColor, borderStyle, borderWidth)
      {
      }

      protected override void WriteDetails(XmlTextWriter writer)
      {
         throw new NotImplementedException();
      }
   }

   internal class ChartStyle : RDLStyle
   {
      public RDLColor BackgroundColor;
      public RDLBackgroundGradient BackgroundGradient;
      public RDLColor BackgroundGradientEndColor;

      public ChartStyle(RDLBorderColor borderColor, RDLBorderStyle borderStyle, RDLBorderWidth borderWidth) 
         : base(borderColor, borderStyle, borderWidth)
      {
      }

      protected override void WriteDetails(XmlTextWriter writer)
      {
         throw new NotImplementedException();
      }
   }

   internal class SubtotalStyle : RDLStyle
   {
      public RDLColor BackgroundColor;
      public RDLImage BackgroundImage;
      public RDLFontStyle FontStyle;
      public RDLFontFamily FontFamily;
      public uint FontSize
      {
         set
         {
            if (IsValidFontSize(value))
               _FontSize = value;
         }
         get
         {
            return _FontSize;
         }
      }
      private uint _FontSize = DefaultFontSize;
      public RDLFontWeight FontWeight;
      public string Format;
      public RDLTextDecoration TextDecoration;
      public RDLTextAlign TextAligh;
      public RDLVerticalAlign VerticalAlign;
      public RDLColor Color;
      public uint LineHeight
      {
         set
         {
            if (IsValidLineHeight(value))
               _LineHeight = value;
         }
         get
         {
            return _LineHeight;
         }
      }
      private uint _LineHeight;
      public bool CanSort;
      public RDLDirection Direction; 
      public RDLUnicodeBiDi UnicodeBiDi;
      public RDLWritingMode WritingMode;

      public SubtotalStyle(RDLBorderColor borderColor, RDLBorderStyle borderStyle, RDLBorderWidth borderWidth) 
         : base(borderColor, borderStyle, borderWidth)
      {
      }

      protected override void WriteDetails(XmlTextWriter writer)
      {
         throw new NotImplementedException();
      }
   }
}
